package py.com.alfa.escriba.gui.controller;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.collections.CollectionUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.context.WebApplicationContext;
import org.thymeleaf.TemplateEngine;
import org.winter.dialect.response.JsonResponse;
import org.winter.utils.command.AjaxResponse;
import org.winter.utils.command.ControllerObject;

import py.com.alfa.escriba.gui.controller.object.gestion.InmueblesControllerObject;
import py.com.alfa.escriba.gui.controller.view.View;
import py.com.alfa.escriba.gui.controller.view.ViewManager;
import py.com.alfa.escriba.gui.dto.gestion.InmueblesDTO;
import py.com.alfa.escriba.gui.dto.gestion.InmuebleslinderosDTO;
import py.com.alfa.escriba.gui.rest.services.InmueblesService;
import py.com.alfa.escriba.gui.services.HelperService;
import py.com.alfa.escriba.gui.services.TabRef;
import py.com.alfa.escriba.gui.session.SystemInfo;
import py.com.alfa.escriba.gui.spring.processors.SpringBean;
import py.com.alfa.escriba.gui.utils.ObjectUtils;
import py.com.sif.rest.client.spring.exception.RestClientException;

@Controller
@Scope("session")
@SessionAttributes("inmuebles")
@RequestMapping("/inmuebles")
public class InmueblesController implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -3529277255508718094L;
	private final static String PAGE_NAME = "pag:inmuebles";
	private final static String CONTROLLER_OBJECT_NAME = "inmuebles";
	
	private Logger log = LoggerFactory.getLogger(getClass());
	@SpringBean private SystemInfo systemInfo;
	@SpringBean private ViewManager viewManager;
	@SpringBean private InmueblesService inmueblesService;
	@SpringBean private HelperService helperService;
	
	@Autowired
	private WebApplicationContext wac;
	
	@Autowired
	private TemplateEngine templateEngine;
	@ControllerObject	
	private InmueblesControllerObject inmuebles;
	private Locale locale;
	
	
	public InmueblesController() {
		this.loadObjects();
	}

	private void loadObjects() {
		setLocale(LocaleContextHolder.getLocale());
	}

	private String verifAuto() {
		Subject subject = SecurityUtils.getSubject();
		if (subject == null || !subject.isAuthenticated()) {
			return "redirect:/";
		}		
		Boolean permitted = subject.isPermitted(InmueblesController.PAGE_NAME);
		systemInfo.setSystemError(false);
		if (!permitted) {
			systemInfo.setSystemError(true);
			systemInfo.setErrorMessage("El usuario no esta autorizado para utilizar este recurso");
			return "error";
		}
		return null;
	}

	
	@ModelAttribute(CONTROLLER_OBJECT_NAME)
	public InmueblesControllerObject getInmuebles() {
		return this.inmuebles;
	}

	public void setInmuebles(InmueblesControllerObject listas) {
		this.inmuebles = listas;
	}

	public Locale getLocale() {
		return locale;
	}

	public void setLocale(Locale locale) {
		this.locale = locale;
	}
	
	/**
	 * Simply selects the home view to render by returning its name.
	 */
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String homePage(Model model, HttpServletRequest request, HttpServletResponse response) {
		this.log.info("inmuebles!");
		try {
			this.getInmuebles().view().disableAll();
			this.getInmuebles().setDepartamentos(this.helperService.getDepartamentos());
			this.getInmuebles().setuMedidas(this.helperService.getTablaRef(TabRef.UM));
			String auto = this.verifAuto();
			if ( auto != null ) {
				return auto;
			}
			loadObject();
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
		}
		return View.INMUEBLES;
	}
	
	private void loadObject(){
		try {
//			this.getVehiculos().setVehiculos(this.vehiculosService.listVehiculos());
			this.getInmuebles().view().enable().lista();
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
		}
	}
	
	@RequestMapping(value = "/departamentoEvent", method = RequestMethod.POST)
	public @ResponseBody JsonResponse departamemtoEvent(Model model, HttpServletRequest request, HttpServletResponse response, 
	      @AjaxResponse(View.INMUEBLES) JsonResponse jResponse, @ModelAttribute(CONTROLLER_OBJECT_NAME) InmueblesControllerObject inmuebles, BindingResult bindingResult) {
		
		this.log.info("INDICADOR DEPARTAMENTO EVENT!");
		try {
			if ( this.getInmuebles().getFiltros().getDepartamento() != null) {
			  Long idDpto = getInmuebles().getFiltros().getDepartamento().getId();
			  this.getInmuebles().setDistritos(this.helperService.getDistritos(idDpto));				
			}			
		} catch (IOException e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jResponse.error(e.getCause().getMessage());
			}
		}
	    
	    return jResponse.success(request, response, wac, model, templateEngine);
	  }	
	@RequestMapping(value = "/dptoEvent", method = RequestMethod.POST)
	public @ResponseBody JsonResponse dptoEvent(Model model, HttpServletRequest request, HttpServletResponse response, 
	      @AjaxResponse(View.INMUEBLE) JsonResponse jResponse, @ModelAttribute(CONTROLLER_OBJECT_NAME) InmueblesControllerObject inmuebles, BindingResult bindingResult) {
		
		this.log.info("INDICADOR DPTO EVENT!");
		try {
			if ( this.getInmuebles().getDepartamento() != null) {
			  Long idDpto = getInmuebles().getDepartamento().getId();
			  this.getInmuebles().setDistritos(this.helperService.getDistritos(idDpto));				
			}
		} catch (IOException e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jResponse.error(e.getCause().getMessage());
			}
		}
	    
	    return jResponse.success(request, response, wac, model, templateEngine);
	  }	

	@RequestMapping(value = "/agregarInmueble", method = RequestMethod.POST)
	public @ResponseBody JsonResponse agregarInmueble(Model model, HttpServletRequest request, HttpServletResponse response, 
			@AjaxResponse(View.INMUEBLES) JsonResponse jResponse, @ModelAttribute(CONTROLLER_OBJECT_NAME) InmueblesControllerObject inmuebles, BindingResult bindingResult) {
		this.log.info("Inmuebles - Nuevo!");
		
		try {
			this.getInmuebles().setInmuebleOri(null);			
			this.getInmuebles().setInmueble(new InmueblesDTO());
			this.getInmuebles().setLindero(new InmuebleslinderosDTO());

		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jResponse.error(e.getCause().getMessage());
			}
			return jResponse.error(e.getMessage());
		}
		
		this.getInmuebles().view().disableAll().enable().inmueble();
		return jResponse.success(request, response, wac, model, templateEngine);
	}
	@RequestMapping(value = "/addLindero", method = RequestMethod.POST)
	public @ResponseBody JsonResponse addLindero(Model model, HttpServletRequest request, HttpServletResponse response, 
		@AjaxResponse(View.INMUEBLE) JsonResponse jResponse, @ModelAttribute(CONTROLLER_OBJECT_NAME) InmueblesControllerObject inmuebles, BindingResult bindingResult) {
		this.log.info("inmueble - addLindero!");
//		try {
		    this.getInmuebles().setLindero(new InmuebleslinderosDTO());
			this.getInmuebles().view().enable().lindero();
//		} catch (IOException e) {
//			this.log.error(e.getMessage(), e);
//			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
//				return jResponse.error(e.getCause().getMessage());
//			}
//		}

		return jResponse.success(request, response, wac, model, templateEngine);
	}	
	

	@RequestMapping(value = "/consultar", method = RequestMethod.POST)
	public @ResponseBody JsonResponse consultar(Model model, HttpServletRequest request, HttpServletResponse response, 
		@AjaxResponse(View.INMUEBLE) JsonResponse jResponse, @ModelAttribute(CONTROLLER_OBJECT_NAME) InmueblesControllerObject inmuebles, BindingResult bindingResult) {
		this.log.info("inmuebles - consultar! {}");
		try {
			this.getInmuebles().setInmuebles(this.inmueblesService.buscarInmuebles(this.getInmuebles().getFiltros()));
			this.getInmuebles().view().disableAll().enable().lista();
			jResponse.setView(View.INMUEBLES);
			} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jResponse.error(e.getCause().getMessage());
			}
		}
		return jResponse.success(request, response, wac, model, templateEngine);
	}
	
	@RequestMapping(value = "/cancelar/{operacion}", method = RequestMethod.POST)
	public @ResponseBody JsonResponse cancelar(Model model, HttpServletRequest request, HttpServletResponse response, 
		@AjaxResponse(View.INMUEBLE) JsonResponse jResponse,  @ModelAttribute(CONTROLLER_OBJECT_NAME) InmueblesControllerObject inmuebles, BindingResult bindingResult, 
		@PathVariable("operacion") String operacion) {
		this.log.info("inmueble- cancelar! {}", operacion);
		
		try {
			if ( operacion == null ) {
				return jResponse.error("Debe informar la operacion a cancelar");
			}
			if ( "INMUEBLE".equals(operacion)) {
				if ( this.getInmuebles().getInmuebleOri() != null) {
					this.getInmuebles().getInmuebles().add(this.getInmuebles().getInmuebleOri());
				}
				this.getInmuebles().setInmuebleOri(null);
			    this.getInmuebles().setInmueble(null);
			    this.getInmuebles().view().disableAll().enable().lista();
			    jResponse.setView(View.INMUEBLES);
			}
			if ( "LINDERO".equals(operacion)) {
//				if ( this.getInmuebles().getLinderoOri()!=null) {
//					this.getInmuebles().getInmuebles().add(this.getInmuebles().getInmuebleOri());
//				}
			    this.getInmuebles().view().disableAll().enable().inmueble();
			}
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jResponse.error(e.getCause().getMessage());
			}
		}
		return jResponse.success(request, response, wac, model, templateEngine);
	}
	@RequestMapping(value = "/guardarLindero", method = RequestMethod.POST)
	public @ResponseBody JsonResponse guardarLindero(Model model, HttpServletRequest request, HttpServletResponse response, 
	      @AjaxResponse(View.INMUEBLE) JsonResponse jResponse, @ModelAttribute(CONTROLLER_OBJECT_NAME) InmueblesControllerObject inmuebles, BindingResult bindingResult) {
		
		this.log.info("GUARDAR LINDERO!");
		//try {
			InmuebleslinderosDTO lindero = new InmuebleslinderosDTO();
			ObjectUtils.copyValues(this.getInmuebles().getLindero(), lindero);
			if(this.getInmuebles().getInmueble().getLinderosList()==null){
				this.getInmuebles().getInmueble().setLinderosList(new ArrayList<InmuebleslinderosDTO>());
			}
			this.getInmuebles().getInmueble().getLinderosList().add(lindero);
			this.getInmuebles().setLindero(null);
			this.getInmuebles().setLinderoOri(null);
			this.getInmuebles().view().disableAll().enable().inmueble();
			log.info("linderos size:"+this.getInmuebles().getInmueble().getLinderosList().size());
			
		//} catch (IOException e) {
//			this.log.error(e.getMessage(), e);
//			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
//				return jResponse.error(e.getCause().getMessage());
//			}
//		}
//	    
	    return jResponse.success(request, response, wac, model, templateEngine);
	  }		
	
	@RequestMapping(value = "/editarLindero/{index}", method = RequestMethod.POST)
	public @ResponseBody JsonResponse editarLindero(Model model,HttpServletRequest request, HttpServletResponse response, 
		         @AjaxResponse(View.INMUEBLE) JsonResponse jResponse, @ModelAttribute(CONTROLLER_OBJECT_NAME) InmueblesControllerObject inmuebles, BindingResult bindingResult, 
		         @PathVariable("index") String ind) {
		this.log.info("\n============== EDITAR Lindero! {}\n==============\n", ind);
		try {
			Integer index = Integer.parseInt(ind);
			InmuebleslinderosDTO obj = this.getInmuebles().getInmueble().getLinderosList().get(index);
			this.log.info("LINDERO: {}", obj);
			this.getInmuebles().setLindero(obj);
			this.getInmuebles().view().enable().lindero();			
			this.getInmuebles().setLinderoOri(obj.clone());
			this.getInmuebles().getInmueble().getLinderosList().remove(obj);			
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jResponse.error(e.getCause().getMessage());
			}
		}
		return jResponse.success(request, response, wac, model, templateEngine);
	}
	
	@RequestMapping(value = "/deleteLindero/{index}", method = RequestMethod.POST)
	public @ResponseBody JsonResponse deleteLindero(Model model,HttpServletRequest request, HttpServletResponse response, 
		         @AjaxResponse(View.INMUEBLE) JsonResponse jResponse, @ModelAttribute(CONTROLLER_OBJECT_NAME) InmueblesControllerObject inmuebles, BindingResult bindingResult, 
		         @PathVariable("index") String ind) {
		this.log.info("\n==============\nELIMINANDO INMUEBLE! {}\n==============\n", ind);
		try {
			Integer index = Integer.parseInt(ind);
			InmuebleslinderosDTO obj = this.getInmuebles().getInmueble().getLinderosList().get(index);
			this.log.info("Linderos: {}", obj);
			this.getInmuebles().getInmueble().getLinderosList().remove(obj);
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jResponse.error(e.getCause().getMessage());
			}
		}
		return jResponse.success(request, response, wac, model, templateEngine);
	}
	
	@RequestMapping(value = "/editarInmueble/{index}", method = RequestMethod.POST)
	public @ResponseBody JsonResponse editarPersona(Model model,HttpServletRequest request, HttpServletResponse response, 
		         @AjaxResponse(View.INMUEBLES) JsonResponse jResponse, @ModelAttribute(CONTROLLER_OBJECT_NAME) InmueblesControllerObject inmuebles, BindingResult bindingResult, 
		         @PathVariable("index") String ind) {
		this.log.info("\n============== EDITAR INMUEBLE! {}\n==============\n", ind);
		try {
			Integer index = Integer.parseInt(ind);
			InmueblesDTO obj = this.getInmuebles().getInmuebles().get(index);
			this.log.info("INMUEBLE: {}", obj);
			InmueblesDTO inmueble = this.inmueblesService.showInmueble(obj.getId());
			this.getInmuebles().setInmueble(inmueble);
//			this.getPersonas().getPersona().setSexoDTO(this.helperService.getTablaRef(TabRef.GENERO, persona.getSexo()));
//			this.getPersonas().getPersona().setTipoPersonaDTO(this.helperService.getTablaRef(TabRef.TIPO_PERSONA, persona.getTipoPersona()));
//			this.getPersonas().setJuridica("JUR".equals(this.getPersonas().getPersona().getTipoPersonaDTO().getCodigo()));
//			
			this.getInmuebles().view().disableAll().enable().inmueble();
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jResponse.error(e.getCause().getMessage());
			}
		}
		return jResponse.success(request, response, wac, model, templateEngine);
	}
	
	@RequestMapping(value = "/deleteInmueble/{index}", method = RequestMethod.POST)
	public @ResponseBody JsonResponse deleteInmueble(Model model,HttpServletRequest request, HttpServletResponse response, 
		         @AjaxResponse(View.INMUEBLES) JsonResponse jResponse, @ModelAttribute(CONTROLLER_OBJECT_NAME) InmueblesControllerObject inmuebles, BindingResult bindingResult, 
		         @PathVariable("index") String ind) {
		this.log.info("\n============== BORRAR INMUEBLE! {}\n==============\n", ind);
		try {
			Integer index = Integer.parseInt(ind);
			InmueblesDTO obj = this.getInmuebles().getInmuebles().get(index);
			this.log.info("INMUEBLE: {}", obj);
			this.inmueblesService.deleteInmueble(obj.getId());
			this.getInmuebles().setInmuebles((this.inmueblesService.buscarInmuebles(this.getInmuebles().getFiltros())));
			this.getInmuebles().view().disableAll().enable().lista();
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jResponse.error(e.getCause().getMessage());
			}
		}
		return jResponse.success(request, response, wac, model, templateEngine);
	}
	
	@RequestMapping(value = "/guardarInmueble", method = RequestMethod.POST)
	public @ResponseBody JsonResponse guardarInmueble(Model model, HttpServletRequest request, HttpServletResponse response, 
			@AjaxResponse(View.INMUEBLE) JsonResponse jResponse, @ModelAttribute(CONTROLLER_OBJECT_NAME) InmueblesControllerObject inmuebles, BindingResult bindingResult){
		this.log.info("GUARDAR INMUEBLE!");
		try {
			
			InmueblesDTO obj = this.getInmuebles().getInmueble();	    			
			if ( CollectionUtils.isEmpty(obj.getLinderosList()) ) {
				return jResponse.error("Debe informar al menos un lindero");
			}
			
			this.log.info("INMUEBLE:{}", obj);
			
			if ( obj.getId() == null ) {
				this.inmueblesService.createInmueble(obj);
			} else {
				this.inmueblesService.saveInmueble(obj);
			}
			this.getInmuebles().setInmuebles(this.inmueblesService.buscarInmuebles(this.getInmuebles().getFiltros()));
			this.getInmuebles().setInmueble(null);
			this.getInmuebles().setInmuebleOri(null);
			this.getInmuebles().view().disableAll().enable().lista();
			jResponse.setView(View.INMUEBLES);
		} catch (Exception e) {
			this.log.error(e.getMessage(), e);
			if (e.getCause() != null && e.getCause() instanceof RestClientException) {
				return jResponse.error(e.getCause().getMessage());
			}
			return jResponse.error(e.getMessage());
		}
		
		return jResponse.success(request, response, wac, model, templateEngine);
	}
	
}	

